package io.wjc.config;

import io.wjc.common.BytesSerializer;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerUtils;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.time.Duration;

import static org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig;

/**
 * Spring Cache 使用 Redis，通过注入RedisConnectionFactory来集成Redis
 * 参考：
 * https://docs.spring.io/spring-data/redis/docs/2.1.17.RELEASE/reference/html/#cluster.redistemplate
 * https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-caching.html
 *
 */
@Configuration
public class CacheConfig {
    /**
     * Redis缓存管理器
     */
    @Bean("RedisCache")
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager cm = RedisCacheManager.builder(connectionFactory)
                //defaultCacheConfig()用来配置Cache
                .cacheDefaults(defaultCacheConfig()
                        //设置20秒过期，默认entryTtl为0，表示永不过期
                        .entryTtl(Duration.ofSeconds(60))
                        .disableCachingNullValues()
                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new BytesSerializer()))
                )
                .transactionAware()
                .build();
        return cm; //RedisCacheManager.create(connectionFactory);
    }

    /**
     * EhCache缓存管理器
     */
    @Bean("EhCache")
    public EhCacheCacheManager EhcacheManager() {
        EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(EhCacheManagerUtils.buildCacheManager());
        return ehCacheManager;
    }

    /**
     * 使用@Primary关键字指定缓存管理类
     * Redis和EhCache的组合缓存管理器：先调用
     */
    @Bean(name = "cacheManager")
    @Primary
    public CompositeCacheManager cacheManager(EhCacheCacheManager ehCacheCacheManager, RedisCacheManager redisCacheManager) {
        CompositeCacheManager cacheManager = new CompositeCacheManager(ehCacheCacheManager, redisCacheManager);
        return cacheManager;
    }

}
